package cn.stylefeng.roses.kernel.secret.modular.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.roses.kernel.auth.api.context.LoginContext;
import cn.stylefeng.roses.kernel.auth.api.password.PasswordStoredEncryptApi;
import cn.stylefeng.roses.kernel.auth.api.pojo.password.SaltedEncryptResult;
import cn.stylefeng.roses.kernel.db.api.factory.PageFactory;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.entity.BaseEntity;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import cn.stylefeng.roses.kernel.rule.enums.StatusEnum;
import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import cn.stylefeng.roses.kernel.secret.modular.entity.SysUserSecretKey;
import cn.stylefeng.roses.kernel.secret.modular.enums.SysUserSecretKeyExceptionEnum;
import cn.stylefeng.roses.kernel.secret.modular.mapper.SysUserSecretKeyMapper;
import cn.stylefeng.roses.kernel.secret.modular.pojo.SysUserSecretKeyRequest;
import cn.stylefeng.roses.kernel.secret.modular.service.SysUserSecretKeyService;
import cn.stylefeng.roses.kernel.sys.modular.user.entity.SysUser;
import cn.stylefeng.roses.kernel.sys.modular.user.service.SysUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * 用户临时秘钥业务实现层
 *
 * @author fengshuonan
 * @date 2022/03/22 11:33
 */
@Service
public class SysUserSecretKeyServiceImpl extends ServiceImpl<SysUserSecretKeyMapper, SysUserSecretKey> implements SysUserSecretKeyService {

    @Resource
    private SysUserService sysUserService;

    @Resource
    private PasswordStoredEncryptApi passwordStoredEncryptApi;

    @Override
    public void add(SysUserSecretKeyRequest sysUserSecretKeyRequest) {

        // 判断只有超级管理员才能操作这个
        if (!LoginContext.me().getSuperAdminFlag()) {
            throw new ServiceException(SysUserSecretKeyExceptionEnum.AUTH_ERROR);
        }

        // 同一个userId不能添加多次秘钥
        Long userId = sysUserSecretKeyRequest.getUserId();
        LambdaQueryWrapper<SysUserSecretKey> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUserSecretKey::getUserId, userId);
        long userKeyCount = this.count(queryWrapper);
        if (userKeyCount > 0) {
            throw new ServiceException(SysUserSecretKeyExceptionEnum.USER_ONLY_ONE_KEY);
        }

        // 创建新增秘钥的信息
        SysUserSecretKey sysUserSecretKey = new SysUserSecretKey();
        BeanUtil.copyProperties(sysUserSecretKeyRequest, sysUserSecretKey);

        // 密码进行加密
        SaltedEncryptResult saltedEncryptResult = passwordStoredEncryptApi.encryptWithSalt(sysUserSecretKey.getSecretKey());
        sysUserSecretKey.setSecretKey(saltedEncryptResult.getEncryptPassword());
        sysUserSecretKey.setSecretKeySalt(saltedEncryptResult.getPasswordSalt());

        this.save(sysUserSecretKey);
    }

    @Override
    public void del(SysUserSecretKeyRequest sysUserSecretKeyRequest) {

        // 判断只有超级管理员才能操作这个
        if (!LoginContext.me().getSuperAdminFlag()) {
            throw new ServiceException(SysUserSecretKeyExceptionEnum.AUTH_ERROR);
        }

        SysUserSecretKey sysUserSecretKey = this.querySysUserSecretKey(sysUserSecretKeyRequest);
        this.removeById(sysUserSecretKey.getUserSecretKeyId());
    }

    @Override
    public PageResult<SysUserSecretKey> findPage(SysUserSecretKeyRequest sysUserSecretKeyRequest) {

        // 判断只有超级管理员才能操作这个
        if (!LoginContext.me().getSuperAdminFlag()) {
            throw new ServiceException(SysUserSecretKeyExceptionEnum.AUTH_ERROR);
        }

        LambdaQueryWrapper<SysUserSecretKey> wrapper = createWrapper(sysUserSecretKeyRequest);
        Page<SysUserSecretKey> sysRolePage = this.page(PageFactory.defaultPage(), wrapper);
        return PageResultFactory.createPageResult(sysRolePage);
    }

    @Override
    public List<SysUser> getUserList(String condition) {

        // 判断只有超级管理员才能操作这个
        if (!LoginContext.me().getSuperAdminFlag()) {
            throw new ServiceException(SysUserSecretKeyExceptionEnum.AUTH_ERROR);
        }

        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getStatusFlag, StatusEnum.ENABLE.getCode());
        queryWrapper.nested(i -> i.like(SysUser::getAccount, condition).or().like(SysUser::getRealName, condition));
        queryWrapper.select(SysUser::getAccount, SysUser::getRealName, SysUser::getUserId);
        return this.sysUserService.list(queryWrapper);
    }

    @Override
    public boolean validateUserTempSecretKey(Long userId, String password) {

        LambdaQueryWrapper<SysUserSecretKey> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUserSecretKey::getUserId, userId);

        // 获取用户秘钥
        SysUserSecretKey sysUserSecretKey = this.getOne(wrapper, false);
        if (sysUserSecretKey == null) {
            return false;
        }

        // 判断是否过期
        Date secretExpirationTime = sysUserSecretKey.getSecretExpirationTime();

        // 如果过期，则删掉这个秘钥
        if (secretExpirationTime.before(new Date())) {
            this.removeById(sysUserSecretKey.getUserSecretKeyId());
            return false;
        }

        // 判断密码是否正确
        String secretKeyMd5 = sysUserSecretKey.getSecretKey();
        String secretKeySalt = sysUserSecretKey.getSecretKeySalt();
        Boolean passwordFlag = passwordStoredEncryptApi.checkPasswordWithSalt(password, secretKeySalt, secretKeyMd5);
        if (!passwordFlag) {
            return false;
        }

        // 判断是否是一次性秘钥，如果是一次性密钥就删除这个密钥记录
        String secretOnceFlag = sysUserSecretKey.getSecretOnceFlag();
        if (YesOrNotEnum.Y.getCode().equals(secretOnceFlag)) {
            this.removeById(sysUserSecretKey.getUserSecretKeyId());
        }

        return true;
    }

    /**
     * 获取信息
     *
     * @author fengshuonan
     * @date 2022/03/22 11:33
     */
    private SysUserSecretKey querySysUserSecretKey(SysUserSecretKeyRequest sysUserSecretKeyRequest) {
        SysUserSecretKey sysUserSecretKey = this.getById(sysUserSecretKeyRequest.getUserSecretKeyId());
        if (ObjectUtil.isEmpty(sysUserSecretKey)) {
            throw new ServiceException(SysUserSecretKeyExceptionEnum.SYS_USER_SECRET_KEY_NOT_EXISTED);
        }
        return sysUserSecretKey;
    }

    /**
     * 创建查询wrapper
     *
     * @author fengshuonan
     * @date 2022/03/22 11:33
     */
    private LambdaQueryWrapper<SysUserSecretKey> createWrapper(SysUserSecretKeyRequest sysUserSecretKeyRequest) {
        LambdaQueryWrapper<SysUserSecretKey> queryWrapper = new LambdaQueryWrapper<>();

        String secretKeyName = sysUserSecretKeyRequest.getSecretKeyName();
        queryWrapper.like(ObjectUtil.isNotEmpty(secretKeyName), SysUserSecretKey::getSecretKeyName, secretKeyName);

        queryWrapper.select(SysUserSecretKey::getSecretKeyName, SysUserSecretKey::getSecretOnceFlag, BaseEntity::getCreateTime,
                SysUserSecretKey::getSecretExpirationTime, SysUserSecretKey::getUserSecretKeyId, SysUserSecretKey::getUserId);

        return queryWrapper;
    }
}
